package ms.maplestory.boot.world;

import ms.maplestory.boot.ServerConstants;
import lombok.Getter;
import lombok.Setter;
import ms.maplestory.boot.client.Client;
import ms.maplestory.boot.client.character.Char;
import ms.maplestory.boot.loaders.FieldData;
import ms.maplestory.boot.util.container.Tuple;
import ms.maplestory.boot.world.field.Field;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;

@Getter
@Setter
public class ChannelServer {

    private String name;
    private int userNo;
    private int worldId;
    private int id;
    private boolean adultChannel;
    private int port;

    public final int MAX_NUMBER = 1000;

    private Map<Integer, Tuple<Integer, Client>> transfers;
    private List<Field> fields;
    private Map<Integer, Char> chars = new HashMap<>();

    public ChannelServer(String name, int userNo, int worldId, int id, boolean adultChannel) {
        this.name = name + "-" + id;
        this.userNo = userNo;
        this.worldId = worldId;
        this.id = id;
        this.adultChannel = adultChannel;
        this.port = ServerConstants.generatorChannelPort(worldId, id);
        this.fields = new CopyOnWriteArrayList<>();
    }

    public Map<Integer, Tuple<Integer, Client>> getTransfers() {
        if (transfers == null) {
            transfers = new ConcurrentHashMap<>();
        }
        return transfers;
    }

    public void addClientInTransfer(int channelId, int characterId, Client client) {
        getTransfers().putIfAbsent(characterId, new Tuple<>(channelId, client));
    }

    public void removeClientFromTransfer(int characterId) {
        getTransfers().remove(characterId);
    }

    public void addChar(Char chr) {
        chars.put(chr.getId(), chr);
    }

    public void removeChar(Char chr) {
        chars.remove(chr.getId());
    }

    public Field getField(int id) {
        for (Field field : fields) {
            if (field.getId() == id) {
                return field;
            }
        }
        return createAndReturnNewField(id);
    }

    private Field createAndReturnNewField(int id) {
        Field newField = FieldData.getFieldCopyById(id);
        if (newField != null) {
            getFields().add(newField);
        }
        return newField;
    }
}
